class CYDateFormat {
  static String formatDate(DateTime date) {
    if(date==null) return "";
    return "${date.year}年${date.month.toString().padLeft(2, '0')}月${date.day.toString().padLeft(2, '0')}日";
  }

  static DateTime fromMillisecondsSinceEpoch(dynamic value) {
    if(value != null && value is int) return DateTime.fromMillisecondsSinceEpoch(value, isUtc: true);
    return null;
  }

  static  DateTime fromZone8StringToUtc(String dateTime) {
    if(dateTime == null) return null;
    if(dateTime.indexOf("+08:00")==-1) {
      dateTime += "+08:00";
    }
    return DateTime.parse(dateTime).toUtc();
  }

  static String toZone8StringFromUtc(DateTime dateTime) {
    if(dateTime == null) return null;
    DateTime zone8DT = dateTime.add(Duration(hours: 8));
    return "${zone8DT.year}-${zone8DT.month.toString().padLeft(2, '0')}-${zone8DT.day.toString().padLeft(2, '0')} ${zone8DT.hour.toString().padLeft(2, '0')}:${zone8DT.minute.toString().padLeft(2, '0')}:${zone8DT.second.toString().padLeft(2, '0')}";
  }

  static String toLocalStringFromUtc(DateTime dateTime) {
    if(dateTime==null) return null;
    DateTime localDT = dateTime.toLocal();
    return "${localDT.year}-${localDT.month.toString().padLeft(2, '0')}-${localDT.day.toString().padLeft(2, '0')} ${localDT.hour.toString().padLeft(2, '0')}:${localDT.minute.toString().padLeft(2, '0')}:${localDT.second.toString().padLeft(2, '0')}";
  }

  static String formatDate2(DateTime dateTime) {
    if(dateTime==null) return null;
    DateTime localDT = dateTime.toLocal();
    return "${localDT.year}-${localDT.month.toString().padLeft(2, '0')}-${localDT.day.toString().padLeft(2, '0')}";
  }

  static String formatDate3(DateTime dateTime) {
    if(dateTime==null) return null;
    DateTime localDT = dateTime.toLocal();
    return "${localDT.month.toString().padLeft(2, '0')}-${localDT.day.toString().padLeft(2, '0')} ${localDT.hour.toString().padLeft(2, '0')}:${localDT.minute.toString().padLeft(2, '0')}";
  }

  static DateTime fromLocalStringToUtc(String dateTime) {
    return DateTime.parse(dateTime).toUtc();
  }

  static int calculateAge(DateTime createAt) {
    DateTime now = DateTime.now().toUtc();
    int dYear = now.year - createAt.year;
    if(dYear<0) return 0;
    
    DateTime yearOld = CYDateFormat.fromZone8StringToUtc("${createAt.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} 00:00:00");
    return yearOld.millisecondsSinceEpoch>createAt.millisecondsSinceEpoch ? dYear : dYear - 1;
  }
}


class CYRelativeDateFormat {
  static const num ONE_MINUTE = 60000;
  static const num ONE_HOUR = 3600000;
  static const num ONE_DAY = 86400000;
  static const num ONE_WEEK = 604800000;

  static const String ONE_SECOND_AGO = "秒前";
  static const String ONE_MINUTE_AGO = "分钟前";
  static const String ONE_HOUR_AGO = "小时前";
  static const String ONE_DAY_AGO = "天前";
  static const String ONE_MONTH_AGO = "月前";
  static const String ONE_YEAR_AGO = "年前";


  static String padLeft(int number, [int width = 2, String padding = '0']) {
    return number?.toString()?.padLeft(width, padding);
  }

  static String durationFormat(Duration duration) {
    if(duration.inHours<=0) {
      return "${padLeft(duration.inMinutes%60)}:${padLeft(duration.inSeconds%60)}";
    } else if(duration.inDays<=0) {
      return "${padLeft(duration.inHours%24)}:${padLeft(duration.inMinutes%60)}:${padLeft(duration.inSeconds%60)}";
    } else {
      return "${duration.inDays}天";
    }
  }

  static String videoDurationFormat({ Duration duration, Duration position }) {
    if(position != null && duration == null) {
      return "${padLeft(position.inMinutes%60)}:${padLeft(position.inSeconds%60)}";
    } 
    if(duration != null && position == null) {
      return "${padLeft(duration.inMinutes%60)}:${padLeft(duration.inSeconds%60)}";
    }  
    return "${padLeft(position.inMinutes%60)}:${padLeft(position.inSeconds%60)} / ${padLeft(duration.inMinutes%60)}:${padLeft(duration.inSeconds%60)}";
  }

  static String msgFormat(DateTime date) {
    if(date == null) return "";
    num delta = DateTime.now().toUtc().millisecondsSinceEpoch - date.toUtc().millisecondsSinceEpoch;
     DateTime localDT = date.toLocal();
    if(delta <= 24*3600*1000) {
      return "${localDT.hour.toString().padLeft(2, '0')}:${localDT.minute.toString().padLeft(2, '0')}";
    } else {
      return CYDateFormat.toLocalStringFromUtc(date);
    }
  }

  /// 时间转换
  static String format(DateTime date) {
    if(date == null) return "";
    num delta = DateTime.now().toUtc().millisecondsSinceEpoch - date.toUtc().millisecondsSinceEpoch;
    if (delta < 1 * ONE_MINUTE) {
      return "刚刚";
      // num seconds = toSeconds(delta);
      // return (seconds <= 0 ? 1 : seconds).toInt().toString() + ONE_SECOND_AGO;
    }
    if (delta < 60 * ONE_MINUTE) {
      num minutes = toMinutes(delta);
      return (minutes <= 0 ? 1 : minutes).toInt().toString() + ONE_MINUTE_AGO;
    }
    if (delta < 24 * ONE_HOUR) {
      num hours = toHours(delta);
      return (hours <= 0 ? 1 : hours).toInt().toString() + ONE_HOUR_AGO;
    }
    if (delta < 48 * ONE_HOUR) {
      return "昨天";
    }
    if (delta < 30 * ONE_DAY) {
      num days = toDays(delta);
      return (days <= 0 ? 1 : days).toInt().toString() + ONE_DAY_AGO;
    }
    if (delta < 12 * 4 * ONE_WEEK) {
      num months = toMonths(delta);
      return (months <= 0 ? 1 : months).toInt().toString() + ONE_MONTH_AGO;
    } else {
      num years = toYears(delta);
      return (years <= 0 ? 1 : years).toInt().toString() + ONE_YEAR_AGO;
    }
  }

  static num toSeconds(num date) {
    return date / 1000;
  }

  static num toMinutes(num date) {
    return toSeconds(date) / 60;
  }

  static num toHours(num date) {
    return toMinutes(date) / 60;
  }

  static num toDays(num date) {
    return toHours(date) / 24;
  }

  static num toMonths(num date) {
    return toDays(date) / 30;
  }

  static num toYears(num date) {
    return toMonths(date) / 365;
  }
}